/**
 * 
 */
package org.statewalker.parser.wiki.parser;

import org.statewalker.dict.BaseDict;
import org.statewalker.parser.base.ParserFactory;
import org.statewalker.parser.wiki.grammar.WikiBlockDict;
import org.statewalker.parser.wiki.grammar.WikiInlineDict;
import org.statewalker.parser.wiki.tokenizer.BlockTokenizer;
import org.statewalker.parser.wiki.tokenizer.InlineTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.DocumentTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.EmptyLineTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.HeaderBeginTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.HeaderEndTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.HorlineTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.ListTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.ParagraphTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.TableCellTokenizer;
import org.statewalker.parser.wiki.tokenizer.block.TableTokenizer;
import org.statewalker.parser.wiki.tokenizer.inline.EscapedTokenizer;
import org.statewalker.parser.wiki.tokenizer.inline.FormatTokenizer;
import org.statewalker.parser.wiki.tokenizer.inline.LinkTokenizer;
import org.statewalker.parser.wiki.validator.WikiValidatorFactory;
import org.statewalker.tokenizer.CompositeTokenizer;
import org.statewalker.tokenizer.ITokenizer;
import org.statewalker.tokenizer.text.TextTokenizer;

/**
 * @author kotelnikov
 */
public class WikiParserFactory extends ParserFactory {

    private ITokenizer BLOCK_DOCUMENT;

    private ITokenizer BLOCK_DOCUMENT_CLOSE;

    private ITokenizer BLOCK_EMPTY_LINE;

    private ITokenizer BLOCK_HEADER;

    private ITokenizer BLOCK_HORLINE;

    private ITokenizer BLOCK_LIST;

    private ITokenizer BLOCK_LIST_CLOSE;

    private ITokenizer BLOCK_PARAGRPAH;

    private ITokenizer BLOCK_PARAGRPAH_CLOSE;

    private ITokenizer BLOCK_TABLE;

    private ITokenizer BLOCK_TABLE_CELL;

    private ITokenizer BLOCK_TABLE_CLOSE;

    private CompositeTokenizer COMPOSITE_BLOCKS;

    private CompositeTokenizer COMPOSITE_INLINE;

    private ITokenizer COMPOSITE_TEXT;

    private ITokenizer INLINE_ESC;

    private ITokenizer INLINE_FORMAT;

    private ITokenizer INLINE_LINK;

    public WikiParserFactory(WikiValidatorFactory validatorFactory) {
        super(validatorFactory);
    }

    @Override
    public void bindTokenizers() {
        // -----------------------------------------------------------------
        // Initalizes basic tokenizers

        // Field initialization
        COMPOSITE_BLOCKS = new BlockTokenizer();
        COMPOSITE_INLINE = new InlineTokenizer();

        // Inline tokenizers
        INLINE_LINK = new LinkTokenizer(WikiInlineDict.A);
        INLINE_ESC = new EscapedTokenizer(WikiInlineDict.ESC);
        INLINE_FORMAT = new FormatTokenizer(WikiInlineDict.STYLE);

        // Block tokenizers
        BLOCK_EMPTY_LINE = new EmptyLineTokenizer(WikiBlockDict.EMPTY_LINES);
        BLOCK_TABLE_CELL = new TableCellTokenizer(
            WikiBlockDict.TR,
            WikiBlockDict.TD);

        BLOCK_TABLE = new TableTokenizer(BLOCK_TABLE_CELL, WikiBlockDict.TABLE);
        BLOCK_TABLE_CLOSE = new EmptyLineTokenizer(WikiBlockDict.TABLE, false);

        BLOCK_HORLINE = new HorlineTokenizer(WikiBlockDict.HR);

        BLOCK_LIST = new ListTokenizer(WikiBlockDict.LI);
        BLOCK_LIST_CLOSE = new EmptyLineTokenizer(WikiBlockDict.UL, false);

        BLOCK_DOCUMENT = new DocumentTokenizer(WikiBlockDict.DOCUMENT, true);
        BLOCK_DOCUMENT_CLOSE = new DocumentTokenizer(
            WikiBlockDict.DOCUMENT,
            false);

        BLOCK_HEADER = new HeaderBeginTokenizer(
            WikiBlockDict.H1,
            WikiBlockDict.H2,
            WikiBlockDict.H3,
            WikiBlockDict.H4,
            WikiBlockDict.H5,
            WikiBlockDict.H6);

        BLOCK_PARAGRPAH = new ParagraphTokenizer(WikiBlockDict.P);
        BLOCK_PARAGRPAH_CLOSE = new EmptyLineTokenizer(WikiBlockDict.P, false);

        // -----------------------------------------------------------------
        // Initialization of composite tokenizers
        // Block
        COMPOSITE_BLOCKS.addTokenizer(BLOCK_TABLE);
        COMPOSITE_BLOCKS.addTokenizer(BLOCK_HORLINE);
        COMPOSITE_BLOCKS.addTokenizer(BLOCK_LIST);
        COMPOSITE_BLOCKS.addTokenizer(BLOCK_HEADER);
        // COMPOSITE_BLOCKS.addTokenizer(BLOCK_PARAGRPAH);

        // Text
        COMPOSITE_TEXT = new TextTokenizer();

        // Inline
        COMPOSITE_INLINE.addTokenizer(INLINE_LINK);
        COMPOSITE_INLINE.addTokenizer(INLINE_ESC);
        COMPOSITE_INLINE.addTokenizer(INLINE_FORMAT);

        // -----------------------------------------------------------------
        // Binding of tokenizers to token keys

        // Sets tokenizers for the ROOT
        setTokenizers(
            BaseDict.ROOT,
            BLOCK_DOCUMENT,
            COMPOSITE_BLOCKS,
            COMPOSITE_INLINE,
            COMPOSITE_TEXT);

        // Internal document
        setTokenizers(WikiBlockDict.DOCUMENT, BLOCK_DOCUMENT_CLOSE);

        // TABLE
        setTokenizers(WikiBlockDict.TABLE, BLOCK_TABLE_CLOSE, BLOCK_TABLE_CELL);

        // LISTS
        setTokenizers(WikiBlockDict.UL, BLOCK_LIST_CLOSE);

        // PARAGRAPH
        setTokenizers(WikiBlockDict.P, BLOCK_PARAGRPAH_CLOSE);

        // Headers (H1, H2, H3, H4, H5, H6)
        setHeaderTokenizers(WikiBlockDict.H1);
        setHeaderTokenizers(WikiBlockDict.H2);
        setHeaderTokenizers(WikiBlockDict.H3);
        setHeaderTokenizers(WikiBlockDict.H4);
        setHeaderTokenizers(WikiBlockDict.H5);
        setHeaderTokenizers(WikiBlockDict.H6);
    }

    private void setHeaderTokenizers(String key) {
        setTokenizers(key, new HeaderEndTokenizer(key));
    }

}